package com.molichuxing.gateway.api.aspect;

import java.lang.reflect.Method;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
import com.molichuxing.gateway.api.config.OptionalLogConfig;
import com.molichuxing.gateway.bff.permission.entity.request.create.OperationLogCreateVo;
import com.molichuxing.gateway.bff.permission.services.OperationLogBffService;
import com.molichuxing.gateway.utils.TokenUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;

@Aspect
@Order(10)
public class LogAopActionAspect {

    private final static Logger logger = LoggerFactory.getLogger(LogAopActionAspect.class);

    /**
     * 注入service,用来将日志信息保存在数据库
     */
    @Resource
    private OperationLogBffService operationLogBffService;

    @Resource
    private TokenUtil tokenUtil;

    /**
     * 配置接入点，即为所要记录的action操作目录
     */
    @Pointcut("execution(* com.molichuxing.gateway.api.services..*.*(..))")
    private void controllerAspect() {
    }

    @Around("controllerAspect()")
    public Object doBefore(ProceedingJoinPoint pjp) throws Throwable {
        //日志实体对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        // 拦截的实体类，就是当前正在执行的controller
        Object target = pjp.getTarget();
        // 拦截的方法名称。当前正在执行的方法
        String methodName = pjp.getSignature().getName();
        // 拦截的放参数类型
        Signature sig = pjp.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod().getParameterTypes();
        // 获得被拦截的方法
        Method method = null;
        try {
            method = target.getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e1) {
            e1.printStackTrace();
        } catch (SecurityException e1) {
            e1.printStackTrace();
        }
       
        
        if (null != method) {
            // 获取方法（此为自定义注解）
            OptionalLogConfig op = method.getAnnotation(OptionalLogConfig.class);
            if(null != op) {
                try{
                	JsonObject json= new JsonObject();
                	String content = request.getQueryString();
                	if(null != content) {
                		json.addProperty("0", content);
                	}
                    ObjectMapper mapper = new ObjectMapper();
                    for (int i=0;i< pjp.getArgs().length; i++) {
    					Object obj = pjp.getArgs()[i];
    					if (obj != null && obj instanceof ServletRequest) {
    						continue;
    					} else if (obj != null && obj instanceof ServletResponse) {
    						continue;
    					} else if (obj != null && obj instanceof BindingResult) {
    						continue;
    					} else if (obj != null && obj instanceof MultipartFile) {
    						continue;
    					} else if (obj != null && obj instanceof MultipartFile[]) {
    						continue;
    					}
    					Integer key= i+1;
    					json.addProperty(key.toString(), mapper.writeValueAsString(obj));
    				}		
                	
                	// 用户token
                    String token = request.getHeader("token");
                	if(StringUtils.isNoneBlank(token)) {
                		// 根据token从redis中获取操作人相关信息
                        UserEntity user = tokenUtil.getUser(token);
                        OperationLogCreateVo operationLog = new OperationLogCreateVo();
                        operationLog.setAction(op.methods());
                        operationLog.setActionUrl(request.getRequestURI());
                        operationLog.setAccountId(user.getAccountId());
                        operationLog.setAccountName(user.getRealName());
                        operationLog.setGroupId(user.getGroupId());
                        operationLog.setGroupName(user.getGroupName());
                        if(json.size() > 0) {
                        	operationLog.setContent(json.toString());
                        }
                        operationLogBffService.createOperationLog(operationLog);
                	}
                }catch(Exception ex) {
                    logger.error("插入操作日志失败");
                }
            }
        }
        return pjp.proceed();
    }
}
